<template>
  <div>
    <div class="app-container" style="height: 100%">
      <el-form
        :model="queryParams"
        ref="queryRef"
        :inline="true"
        v-show="showSearch"
      >
        <el-form-item label="设备名称" prop="deviceName">
          <el-input
            v-model="queryParams.deviceName"
            placeholder="请输入设备名称"
            clearable
            style="width: 200px"
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item label="设备类型" prop="deviceTypeId">
          <el-select v-model="queryParams.deviceTypeId">
            <el-option
              v-for="item in deviceTypeList"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" @click="handleQuery"
            >搜索</el-button
          >
          <el-button type="primary" icon="Refresh" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>

      <el-row :gutter="10" class="mb8">
        <el-col :span="1.5">
          <el-button type="primary" plain icon="Plus" @click="handleAdd"
            >新增</el-button
          >
        </el-col>
        <right-toolbar
          v-model:showSearch="showSearch"
          @queryTable="getList"
        ></right-toolbar>
      </el-row>

      <el-table v-loading="loading" stripe :data="tableData">
        <el-table-column prop="deviceName" align="center" label="设备名称" />
        <el-table-column
          prop="deviceCode"
          align="center"
          width="180"
          label="设备编码"
        />
        <el-table-column
          prop="deviceCodeId"
          align="center"
          label="设备编号Id"
        />
        <el-table-column prop="channelName" align="center" label="渠道名称" />
        <el-table-column align="center" prop="deptName" label="设备行政" />
        <el-table-column
          label="设备类型"
          align="center"
          prop="deviceTypeName"
        />
        <el-table-column label="经度" align="center" prop="longitude" />
        <el-table-column label="维度" align="center" prop="latitude" />
        <el-table-column label="设备厂家" align="center" prop="factoryName" />
        <el-table-column prop="state" label="设备状态">
          <template #default="scope">
            {{ scope.row.state == 0 ? "正常" : "异常" }}
          </template>
        </el-table-column>
        <el-table-column label="是否有摄像头" align="center" prop="videoType">
          <template #default="scope">
            {{ scope.row.videoType == 0 ? "无" : "有" }}
          </template>
        </el-table-column>
        <el-table-column
          v-if="
            queryParams.deviceTypeId &&
            deviceTypeList.find((item) => item.id === queryParams.deviceTypeId)
              ?.type === 200
          "
          label="闸门最大开度(m)"
          align="center"
          prop="deviceKaidu"
        >
          <template #default="scope">
            {{ scope.row.deviceKaidu || "-" }}
          </template>
        </el-table-column>
        <el-table-column
          label="备注"
          show-overflow-tooltip
          align="center"
          prop="remark"
        />

        <el-table-column prop="snapshot" label="设备照片">
          <template #default="scope">
            <el-image
              style="width: 30px; height: 30px"
              :preview-src-list="[scope.row.snapshot]"
              :src="scope.row.snapshot"
              fit="fill"
            >
            </el-image>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          fixed="right"
          width="250px"
          class-name="small-padding fixed-width"
        >
          <template #default="scope">
            <el-button
              link
              type="primary"
              icon="Setting"
              @click="handleSetThreshold(scope.row)"
              >设置设备报警阈值</el-button
            >
            <!-- <el-button
              link
              type="primary"
              icon="View"
              @click="handleView(scope.row)"
              >动态属性</el-button
            > -->
            <el-button
              link
              type="primary"
              icon="Edit"
              @click="handleUpdate(scope.row)"
              >修改</el-button
            >

            <el-button
              link
              type="primary"
              icon="Delete"
              @click="handleDelete(scope.row)"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>

      <!-- 添加或修改图层对话框 -->
      <el-dialog
        :title="title"
        v-model="open"
        width="800px"
        append-to-body
        destroy-on-close
      >
        <el-form
          ref="deviceRef"
          :model="form"
          :rules="rules"
          label-width="120px"
        >
          <el-row v-if="!form.id" :gutter="20">
            <el-col :span="24">
              <el-form-item label="设备类型" prop="deviceTypeId">
                <el-select
                  v-model="form.deviceTypeId"
                  @change="deviceTypeChange"
                >
                  <el-option
                    v-for="item in deviceTypeList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  ></el-option>
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="设备名称" prop="deviceName">
                <el-input
                  v-model="form.deviceName"
                  placeholder="请输入设备名称"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="设备编码" prop="deviceCode">
                <el-input
                  v-model="form.deviceCode"
                  placeholder="请输入设备编码"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="设备编号Id" prop="deviceCodeId">
                <el-input
                  v-model="form.deviceCodeId"
                  placeholder="请输入设备编号Id"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="设备厂商" prop="factoryId">
                <el-select v-model="form.factoryId">
                  <el-option
                    v-for="item in deviceFactoryList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.id"
                  ></el-option>
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="经度" prop="longitude">
                <el-input v-model="form.longitude" placeholder="请输入经度" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="维度" prop="latitude">
                <el-input v-model="form.latitude" placeholder="请输入维度" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="渠道" prop="channelId">
                <el-tree-select
                  v-model="form.channelId"
                  check-strictly
                  :data="qdTree"
                  filterable
                  :filter-node-method="filterNodeMethod"
                  placeholder="请搜索或选择渠道"
                  clearable
                  popper-class="custom-tree-select-dropdown"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="行政" prop="deptId">
                <el-tree-select
                  v-model="form.deptId"
                  check-strictly
                  :data="deptTree"
                  filterable
                  :filter-node-method="filterNodeMethod"
                  placeholder="请搜索或选择行政区域"
                  clearable
                  popper-class="custom-tree-select-dropdown"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="备注" prop="remark">
                <el-input
                  :rows="3"
                  type="textarea"
                  v-model="form.remark"
                  placeholder="请输入备注"
                />
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="是否有摄像头" prop="videoType">
                <el-select v-model="form.videoType" placeholder="请选择">
                  <el-option label="无" :value="0" />
                  <el-option label="有" :value="1" />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <template v-if="form.videoType === 1">
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="摄像头A" prop="videoCodeA">
                  <el-input
                    v-model="form.videoCodeA"
                    placeholder="请输入摄像头A编码"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="摄像头B" prop="videoCodeB">
                  <el-input
                    v-model="form.videoCodeB"
                    placeholder="请输入摄像头B编码"
                  />
                </el-form-item>
              </el-col>
            </el-row>

            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="摄像头C" prop="videoCodeC">
                  <el-input
                    v-model="form.videoCodeC"
                    placeholder="请输入摄像头C编码"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="摄像头D" prop="videoCodeD">
                  <el-input
                    v-model="form.videoCodeD"
                    placeholder="请输入摄像头D编码"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </template>

          <!-- 闸门专用字段 -->
          <template v-if="isGateDevice">
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="闸门最大开度" prop="deviceKaidu">
                  <el-input
                    v-model="form.deviceKaidu"
                    type="number"
                    step="0.01"
                    placeholder="请输入闸门最大开度"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </template>

          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="设备照片" prop="snapshot">
                <el-upload
                  class="avatar-uploader"
                  action="/dev-api/common/oss/upload"
                  :show-file-list="false"
                  :headers="{
                    'X-Noodle-Token': getToken(),
                    Authorization: 'Bearer ' + getToken(),
                  }"
                  :on-success="handleAvatarSuccess"
                  :before-upload="beforeAvatarUpload"
                >
                  <img
                    v-if="form.snapshot"
                    :src="form.snapshot"
                    class="avatar"
                  />
                  <el-icon v-else class="avatar-uploader-icon"
                    ><Plus
                  /></el-icon>
                  <template #tip>
                    <div style="font-size: 12px; color: #999">
                      仅支持 JPG/PNG 格式，大小不超过 500KB。<br />
                    </div>
                  </template>
                </el-upload>
              </el-form-item>
            </el-col>
          </el-row>

          <!-- 动态属性 -->
          <div
            v-if="isLoadingDynamicProps"
            style="text-align: center; padding: 20px"
          >
            <el-icon class="is-loading"><Loading /></el-icon>
            <span style="margin-left: 8px">正在加载设备属性...</span>
          </div>
          <transition-group v-else name="fade-slide" tag="div">
            <template
              v-for="(item, index) in form.devicePropertyDataList"
              :key="`${item.id}-${updateKey}`"
            >
              <el-row :gutter="20" v-if="index % 2 === 0">
                <el-col :span="12">
                  <el-form-item
                    :label="item.propertyName"
                    :prop="item.propertyCode"
                  >
                    <el-input v-model="item.valueString"></el-input>
                  </el-form-item>
                </el-col>
                <el-col
                  :span="12"
                  v-if="form.devicePropertyDataList[index + 1]"
                >
                  <el-form-item
                    :label="form.devicePropertyDataList[index + 1].propertyName"
                    :prop="form.devicePropertyDataList[index + 1].propertyCode"
                  >
                    <el-input
                      v-model="
                        form.devicePropertyDataList[index + 1].valueString
                      "
                    ></el-input>
                  </el-form-item>
                </el-col>
              </el-row>
            </template>
          </transition-group>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button type="primary" @click="submitForm">确 定</el-button>
            <el-button @click="cancel">取 消</el-button>
          </div>
        </template>
      </el-dialog>
    </div>
    <!-- 分页 -->
    <el-pagination
      style="float: right"
      @current-change="currentChange"
      :current-page="pagination.curPage"
      :page-size="pagination.pageSize"
      layout="total, prev, pager, next"
      :total="pagination.total"
    />
    <el-dialog
      title="查看设备详情"
      v-model="detailShow"
      width="800px"
      append-to-body
      destroy-on-close
    >
      <el-form :model="form" inline label-width="120px">
        <el-form-item label="设备名称" prop="deviceName">
          <div
            style="
              width: 200px;
              height: 32px;
              line-height: 32px;
              color: rgb(11, 94, 148);
            "
          >
            {{ form.deviceName }}
          </div>
        </el-form-item>
        <el-form-item label="设备编码" prop="deviceCode">
          <div
            style="
              width: 200px;
              height: 32px;
              line-height: 32px;
              color: rgb(11, 94, 148);
            "
          >
            {{ form.deviceCode }}
          </div>
        </el-form-item>
        <el-form-item label="经度" prop="longitude">
          <div
            style="
              width: 200px;
              height: 32px;
              line-height: 32px;
              color: rgb(11, 94, 148);
            "
          >
            {{ form.longitude }}
          </div>
        </el-form-item>
        <el-form-item label="维度" prop="latitude">
          <div
            style="
              width: 200px;
              height: 32px;
              line-height: 32px;
              color: rgb(11, 94, 148);
            "
          >
            {{ form.latitude }}
          </div>
        </el-form-item>
        <el-form-item
          v-if="form.deviceKaidu"
          label="闸门最大开度"
          prop="deviceKaidu"
        >
          <div
            style="
              width: 200px;
              height: 32px;
              line-height: 32px;
              color: rgb(11, 94, 148);
            "
          >
            {{ form.deviceKaidu }}
          </div>
        </el-form-item>
        <el-form-item
          v-for="item in form.devicePropertyDataList"
          :key="item.id"
          :label="item.propertyName"
          :prop="item.propertyCode"
        >
          <div
            style="
              width: 200px;
              height: 32px;
              line-height: 32px;
              color: rgb(11, 94, 148);
            "
          >
            {{ item.valueString }}
          </div>
        </el-form-item>
      </el-form>
    </el-dialog>
    <setDevice ref="setDeviceRef" />
  </div>
</template>

<script setup>
import { getDeviceTypeList, getEmptyByType } from "@/api/deviceType";
import {
  getDeviceList,
  delDevice,
  getDeviceDetailById,
  saveDevice,
} from "@/api/device";
import { getToken } from "@/utils/auth";
import { ElMessage, ElMessageBox } from "element-plus";
import { reactive, watch, computed, nextTick } from "vue";
import { getDeviceFactoryList } from "@/api/deviceFactory";
import { listDept } from "@/api/system/dept";
import { getQdTree } from "@/api/qdTree";
import { buildTree } from "@/utils/index";
import setDevice from "@/views/device/setDevice.vue";
import { Loading } from "@element-plus/icons-vue";
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const title = ref("");
const detailShow = ref(false);
const setDeviceRef = ref();
const updateKey = ref(1);
let deviceTypeList = ref([]);
let deviceFactoryList = reactive([]);
let deptTree = reactive([]);
let qdTree = reactive([]);
let dynamicPropertyList = reactive([]);
const isLoadingDynamicProps = ref(false);

const queryParams = reactive({
  deviceName: "",
  deviceTypeId: null,
});
const handleSetThreshold = (row) => {
  setDeviceRef.value.openDialog(row);
};
getDeviceTypeList().then((res) => {
  deviceTypeList.value = res.data.list;
});
getDeviceFactoryList({
  curPage: 1,
  pageSize: 100,
}).then((res) => {
  deviceFactoryList = res.data.list;
});
listDept().then((res) => {
  deptTree = buildTree(res.data, "deptId", "deptName", "parentId");
});
getQdTree().then((res) => {
  qdTree = transformData(res.data);
});

// 转换渠道数据结构
function transformData(data) {
  return data.map((item) => ({
    value: item.id,
    label: item.name,
    children: item.childList ? transformData(item.childList) : [], // 递归处理子节点
  }));
}

// 判断是否为闸门设备
const isGateDevice = computed(() => {
  if (!form.deviceTypeId || !deviceTypeList.value.length) return false;
  const currentDeviceType = deviceTypeList.value.find(
    (item) => item.id === form.deviceTypeId
  );
  // 闸门设备类型的type值为200
  return currentDeviceType?.type === 200;
});

const pagination = reactive({
  curPage: 1,
  pageSize: 10,
  total: 0,
});
const kindList = [
  {
    label: "硬件属性",
    value: 0,
  },
  {
    label: "数据属性",
    value: 1,
  },
];
const dataTypeList = [
  {
    label: "字符串",
    value: 0,
  },
  {
    label: "整数型",
    value: 1,
  },
  {
    label: "小数型",
    value: 2,
  },
  {
    label: "布尔型",
    value: 3,
  },
  {
    label: "日期型",
    value: 10,
  },
];
const propertyForm = reactive({
  name: "",
  dataCode: "",
  dataType: 0,
  kind: 0,
});
const data = reactive({
  rules: {
    name: [{ required: true, message: "设备名称不能为空", trigger: "blur" }],
    typeCode: [
      { required: true, message: "设备编码不能为空", trigger: "blur" },
    ],
  },
  propRules: {
    name: [{ required: true, message: "属性名称不能为空", trigger: "blur" }],
    dataCode: [
      { required: true, message: "属性编码不能为空", trigger: "blur" },
    ],
  },
});
function setDynamicProperty() {
  isLoadingDynamicProps.value = true;
  getEmptyByType({ typeId: form.deviceTypeId })
    .then((res) => {
      // 避免频繁更新，先清空再赋值
      form.devicePropertyDataList = [];
      nextTick(() => {
        form.devicePropertyDataList = [...res.data.devicePropertyDataList];
        form.devicePropertyDataList.forEach((d) => {
          if (d.dataFormContent) d.valueString = d.dataFormContent;
        });
        updateKey.value++;
        isLoadingDynamicProps.value = false;
      });
    })
    .catch(() => {
      isLoadingDynamicProps.value = false;
    });
}
function handleView(row) {
  reset();
  getDeviceDetailById(row.id).then((res) => {
    Object.assign(form, res.data);
    detailShow.value = true;
  });
}
const handleAvatarSuccess = (res, uploadFile) => {
  ElMessage({
    message: "上传成功！",
    type: "success",
  });
  form.snapshot = res.data.fileUrl || res.data.link || res.data.url;
};
const beforeAvatarUpload = (file) => {
  const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";
  const isLt200k = file.size / 1024 < 500;

  if (!isJpgOrPng) {
    ElMessage.error("上传图片格式应为 JPG 或 PNG!");
  }
  if (!isLt200k) {
    ElMessage.error("上传图片大小不能超过 200KB!");
  }
  return isJpgOrPng && isLt200k;
};
const { rules, propRules } = toRefs(data);
const form = reactive({
  id: null,
  deviceName: "",
  deviceCode: "",
  deviceCodeId: null,
  factoryId: "",
  channelId: "",
  deptId: "",
  deviceTypeId: null,
  remark: "",
  snapshot: "",
  latitude: "",
  longitude: "",
  devicePropertyDataList: [],
  videoType: 0,
  videoCodeA: "",
  videoCodeB: "",
  videoCodeC: "",
  videoCodeD: "",
  deviceKaidu: "",
});
function getNameByType(type) {
  return dataTypeList.filter((f) => f.value == type)[0].label;
}
/** 查询列表 */
function getList() {
  loading.value = true;
  let params = { ...pagination, ...queryParams };
  getDeviceList(params).then((response) => {
    tableData.value = response.data.list;
    pagination.total = response.data.totalCount;
    loading.value = false;
  });
}
/** 取消按钮 */
function cancel() {
  open.value = false;
  reset();
}

/** 表单重置 */
function reset() {
  Object.assign(form, {
    id: null,
    deviceName: "",
    deviceCode: "",
    deviceTypeId: null,
    factoryId: "",
    channelId: "",
    deptId: "",
    latitude: "",
    longitude: "",
    remark: "",
    snapshot: "",
    devicePropertyDataList: [],
    videoType: 0,
    videoCodeA: "",
    videoCodeB: "",
    videoCodeC: "",
    videoCodeD: "",
    deviceKaidu: "",
  });
  if (deviceTypeList.length) form.deviceTypeId = deviceTypeList.value[0].id;
  proxy.resetForm("deviceRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  queryParams.deviceName = "";
  handleQuery();
}

/** 新增按钮操作 */
function handleAdd(row) {
  reset();
  if (form.deviceTypeId) {
    setDynamicProperty();
  }
  open.value = true;
  title.value = "新增设备";
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  getDeviceDetailById(row.id).then((res) => {
    Object.assign(form, res.data);
    open.value = true;
    title.value = "修改设备";
  });
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["deviceRef"].validate((valid) => {
    if (valid) {
      if (form.id) {
        saveDevice(form).then((response) => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        saveDevice(form).then((response) => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  ElMessageBox.confirm(
    '是否确认删除名称为"' + row.deviceName + '"的数据项?',
    "提示",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }
  )
    .then(() => {
      delDevice([row.id]).then((res) => {
        getList();
        proxy.$modal.msgSuccess("删除成功");
      });
    })
    .catch(() => {
      ElMessage.info("取消删除");
    });
}
function currentChange(e) {
  pagination.curPage = e;
  getList();
}
function deviceTypeChange(e) {
  if (e) {
    // 使用 nextTick 确保 DOM 更新完成后再执行
    nextTick(() => {
      setDynamicProperty();
    });
  }
}
function filterNodeMethod(value, data) {
  if (!value) return true;
  // 支持多种字段名的搜索，不区分大小写
  const searchText = data.label || data.name || data.deptName || "";
  const result = searchText.toLowerCase().includes(value.toLowerCase());
  return result;
}
getList();
</script>
<style lang="scss" scoped>
.avatar-uploader .avatar {
  width: 100px;
  height: 100px;
  display: block;
}
.avatar {
  width: 100px;
  height: 100px;
  display: block;
}
.avatar-uploader :deep(.el-upload) {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.avatar-uploader :deep(.el-upload:hover) {
  border-color: var(--el-color-primary);
}

:deep(.el-icon.avatar-uploader-icon) {
  font-size: 28px;
  color: #8c939d;
  width: 100px;
  height: 100px;
  text-align: center;
}
.el-select {
  width: 220px !important;
}
.el-input {
  width: 100% !important;
}
.el-textarea {
  width: 100% !important;
}
.el-tree-select {
  width: 100% !important;
}

/* 过渡动画样式 */
.fade-slide-enter-active,
.fade-slide-leave-active {
  transition: all 0.3s ease;
}
.fade-slide-enter-from {
  opacity: 0;
  transform: translateX(10px);
}
.fade-slide-leave-to {
  opacity: 0;
  transform: translateX(-10px);
}
.fade-slide-move {
  transition: transform 0.3s ease;
}
</style>
<style>
:deep(.el-dialog) {
}
:deep(.custom-tree-select-dropdown) {
  max-height: 300px !important;
  min-width: 280px !important;
}
:deep(.custom-tree-select-dropdown .el-tree-select-dropdown__list) {
  max-height: 280px !important;
  overflow-y: auto !important;
  min-width: 280px !important;
}
:deep(.custom-tree-select-dropdown .el-scrollbar__view) {
  max-height: 280px !important;
  min-width: 280px !important;
}
:deep(.custom-tree-select-dropdown .el-tree) {
  max-height: 280px !important;
  overflow-y: auto !important;
  min-width: 280px !important;
}
:deep(.el-tree-select-dropdown__list) {
  max-height: 280px !important;
  overflow-y: auto !important;
  min-width: 280px !important;
}
:deep(.el-tree-node__content) {
  white-space: nowrap !important;
  min-width: 250px !important;
}
:deep(.el-tree-node__label) {
  white-space: nowrap !important;
  overflow: visible !important;
}
</style>
